<?php
/*
access control events
based on uriAccessControl, uriPermissions, userManager & groupManager classes

file version 2005-10-18 16:53:24
*/
class uriGuardian {
/*--------------------------------------------------------------------------------------------------
                                                                                         constructor
--------------------------------------------------------------------------------------------------*/
	function uriGuardian() {
		//load config
		$this->loadConfig();
		// echo wakaffvar($this->cfg,'uri guardian config');
	}
/*--------------------------------------------------------------------------------------------------
                                                                                      public methods
--------------------------------------------------------------------------------------------------*/
	/* checks for access rights on current uri (or $p['uri'])
	if access is not granted, throws appropriate 401/403 page and shut down
	else return true and sets user/session info
	*/
	function filterAccess($p=array()) {
		//echo wakaffvar($_COOKIE);
		if (isset($p['uri'])) $uri=$p['uri'];
		else $uri=CALL_URI;
		// getting logged user
		if ($user=$this->getLoggedUser())
			$this->setConstants();
		
		// if uri is public then access is granted without more checks
		if ($this->isUriPublic($uri)) return true;
		// tries to find a logged user
		if (!$user
		// tries to log in a user if necessary
		and !$this->tryLogUser()) {
		// still no user logged in ? throwing 401 page
			//$this->destroySessionKey();
			/*$userAuthSessionM=& $this->getUserAuthSessionM();
			define('AUTHSESSION_WHYUNLOGGED',$userAuthSessionM->whyUnlogged());*/
			$this->throw401();
			return true();
		}
		// login out ?
		if ($logout=wakGetVarIn($this->cfg['authSessions']['logoutKey'],'get_post')) {
			// echo "<p>login out</p>";
			$loggedOut=$this->logOut();
			// echo wakaffvar($loggedOut,' logged out');
			if ($loggedOut)
				$this->throwLogout();
			return true();
		}
		// storing session key
		$this->storeSessionKey();
		// using groups ?
		if ($this->cfg['groups']['use']) {
			// search user groups
			$this->user['groups']=$this->getUserGroups($this->user['id']);
			// array keys are group ids
			$groupsIds=array_keys($this->user['groups']);
			// echo wakAffvar($this->user);
			// checks for groups permissions on uri
			if (!$this->areGroupsAllowedOnUri($groupsIds,$uri)) {
				$this->setConstants();
				$this->throw403();
				return true;
			}
		} else {
			// checks for user permissions on uri
			if (!$this->isUserAllowedOnUri($this->user['id'],$uri)) {
				$this->setConstants();
				$this->throw403();
				return true();
			}
		}
		
		/*trigger_error("access denied");
		wakShutDown();*/
		//echo wakaffvar($this->user,'user');
		//echo wakaffvar($this->session,'session');
		$this->setConstants();
		return true;
	}
	/* tries to retrieve currently logged user if possible
	*/
	function getLoggedUser() {
		// searching for key
		if (!$key=$this->searchSessionKey()) {
			return false;
		}
		// checking session
		$userAuthSessionM=& $this->getUserAuthSessionM();
		if (!$this->session=$userAuthSessionM->check($key)) {
			waklog("destroying obsolete key $key");
			$this->destroySessionKey();
			return false;
		}
		waklog('found session key '.$key);
		// getting user
		if (!$this->user=$this->getUserById($this->session['user_id'])) {
			waklog('failed to find user for session '.$key);
			return false;
		}
		return true;
	}
	/* search for a user with login and pwd
	if login and/or pwd are not provided, search for them in post vars
	if a user is found with correct pwd, opens a authentication session
	keep user and session infos into wak vars userInfo and authSessionInfo
	returns userId if everything ok
	*/
	function tryLogUser($login=NULL, $pwd=NULL) {
		// searching for args in post data
		if (!$login) $login=wakGetVarIn('login','post');
		if (!$pwd) $pwd=wakGetVarIn('pwd','post');
		// still no args ?
		if (!$login or !$pwd) return false;
		// checking user
		if (!$this->user=$this->getUserByLoginPwd($login, $pwd))
			return false;
		$userAuthSessionM=& $this->getUserAuthSessionM();
		// trying to open auth session
		if (!$this->session=$userAuthSessionM->open($this->user['id']))
			return false;
		// storing session key
		return true;
	}
	/*
	*/
	/*function tryHttpLogin() {
	
	}*/
	/*
	* /
	function userInfo() {
	
	}
	/*
	* /
	function getKey() {
	
	}
	/*
	*/
	function logOut() {
		if (!$key=$this->searchSessionKey()) return false;
		// echo wakaffvar($key,'session key');
		$userAuthSessionM=& $this->getUserAuthSessionM();
		if (!$userAuthSessionM->close($key)) return false;
		$this->destroySessionKey();
		return true;
	}
	/*
	*/
	function isUserAllowedOnUri($userId,$uri) {
		$uriPM=&$this->getUriPM();
		return $uriPM->checkIdOnUri($userId,$uri);
	}
	/*
	*/
	function isUriPublic($uri=NULL) {
		$uriPM=&$this->getUriPM();
		return $uriPM->isUriPublic($uri);
	}
	/*
	*/
	function areGroupsAllowedOnUri($groupIds,$uri) {
		$uriPM=&$this->getUriPM();
		return $uriPM->checkIdsOnUri($groupIds,$uri);
	}
	/*
	*/
	/*function () {
		
	}*/
/*--------------------------------------------------------------------------------------------------
                                                                                          properties
--------------------------------------------------------------------------------------------------*/
	var $cfgFile='cfg/uriguardian.config.ini';
	var $cfg=array(
		'templates'=>array(
			'401'=>'xhtml/401.template.xhtml'
			, '403'=>'xhtml/403.template.xhtml'
			, 'logout'=>'xhtml/logout.template.xhtml')

		// auth sessions params
		, 'authSessions'=>array(
			'keyName'=>'authSessionKey'
			, 'setCookie'=>true
			, 'setConstant'=>true
			, 'logoutKey' => 'logout')
			
		// auth session storag eparam
		, 'userAuthSession'=>array(
			'tableName'=>'auth_sessions')
		
		// users table data
		, 'users'=>array(
			'tableName'=>'users'
			, 'pwdEncryption'=>'md5'
			, 'idField'=>'id'
			, 'loginField'=>'login'
			, 'pwdField'=>'password')
			
		// groups use and table data
		, 'groups'=>array(
			'use'=>false
			,'tableName'=>'groups'
			,'idField'=>'id'
			,'nameField'=>'name')
			
		// link users-groups table data
		, 'usersGroups'=>array(
			'tableName'=>'users_groups'
			,'userIdField'=>'user_id'
			, 'groupIdField'=>'group_id')
			
		, 'permissionManager'=>array(
			'default'=>'allow'
			,'tableName'=>'uri_permissions')
	);
	var $user=false; // user row information
	var $authSession=false; // auth session information
	var $userGroups=false; // user groups
	var $session; // bool ?
/*--------------------------------------------------------------------------------------------------
                                                                                     private methods
--------------------------------------------------------------------------------------------------*/
	/* try to import config
	cfg can be an array, the path to a ini file or null
	in which case it will try to load cfg/{self class name}.config.ini
	*/
	function loadConfig($cfg=NULL,$sections=true) {
		if ($cfg==NULL)
			$cfg='cfg/'.get_class($this).'.config.ini';
		if (is_string($cfg) and is_file($cfg))
			$cfg=parse_ini_file($cfg,$sections);
		if (is_array($cfg)) {
			$this->cfg=wakArrayMergeRR($this->cfg,$cfg);
			return true;
		}
		return false;
	}
	/*
	*/
	/*function () {
		
	}*/
	
	/*
	*/
	function getUserById($id) {
		$sql="SELECT *"
		.", ".$this->cfg['users']['idField']." AS id"
		.", ".$this->cfg['users']['pwdField']." AS pwd"
		." FROM ".$this->cfg['users']['tableName']
		." WHERE id=".wakSqlSecureValue($id);
		return wakSqlUniqueResult($sql);
	}
	
	/*
	*/
	function getUserByLoginPwd($login,$pwd) {
		$sql="SELECT *"
		.", ".$this->cfg['users']['idField']." AS id"
		.", ".$this->cfg['users']['pwdField']." AS pwd"
		." FROM ".$this->cfg['users']['tableName']
		.' WHERE '.$this->cfg['users']['loginField'].'='.wakSqlSecureValue($login);
		if (!$user=wakSqlUniqueResult($sql)) return false;
		// checking pwd
		if ($this->cfg['users']['pwdEncryption']=='md5') $pwd=md5($pwd);
		if ($pwd!=$user['pwd']) return false;
		else return $user;
		//return wakRunEvent('users->getbyloginpwd',array('login'=>$login,'pwd'=>$pwd));
	}
	
	function getUserGroups($userId) {
		$userId=wakSqlSecureValue($userId);
		$sql='SELECT u_g.'.$this->cfg['usersGroups']['groupIdField'].' AS id'
		.', g.'.$this->cfg['groups']['nameField'].' AS name'
		.' FROM '.$this->cfg['usersGroups']['tableName'].' AS u_g'
		.' LEFT OUTER JOIN '.$this->cfg['groups']['tableName'].' AS g'
		.' ON g.'.$this->cfg['groups']['idField'].'=u_g.'.$this->cfg['usersGroups']['groupIdField']
		.' WHERE u_g.'.$this->cfg['usersGroups']['userIdField'].'='.$userId;
		return wakSqlResult($sql,'id');
	}
	/**
	*
	* /
	function openAuthSession($userId) {
		
	}/**/
	
	// returns the uriPermissionManager singleton
	function & getUriPM() {
		if (isset($this->cfg['permissionManager'])) $cfg=$this->cfg['permissionManager'];
		else $cfg=NULL;
		$uriPM=wakNeedSingleton('uripermissionmanager',$cfg);
		return $uriPM;
	}
	
	// returns the userAuthSession singleton
	function & getUserAuthSessionM() {
		if (isset($this->cfg['userAuthSession'])) $cfg=$this->cfg['userAuthSession'];
		else $cfg=NULL;
		$obj=wakNeedSingleton('userAuthSession',$cfg);
		return $obj;
	}
	
	function searchSessionKey() {
		//$key=wakGetVarIn($this->cfg['authSessions']['keyName'],'cookie');
		$name=$this->cfg['authSessions']['keyName'];
		$key=isset($_COOKIE[$name])?$_COOKIE[$name]:null;
		if (!$key)
			waklog('no session key found, '.$name.wakaffvar($_COOKIE[$name]));
		// echo wakaffvar($key,'searched key');
		return $key;
	}
	
	function storeSessionKey() {
		// checking session validity
		if (!$this->session 
		or !isset($this->session['key']) 
		or !isset($this->session['limit_date'])
		or !isset($this->session['key']))
			return false;
		// storing
		$key=$this->cfg['authSessions']['keyName'];
		$value=$this->session['key'];
		// storing in system var
		wakSetVar($key,$value);
		// storing in cookie
		if ($this->cfg['authSessions']['setCookie']) {
			
			
			$expire=wakDateConvert('php_timestamp',$this->session['limit_date']);
			return setCookie($key,$value,$expire,'/');
		}
		return false;
	}
	
	function destroySessionKey() {
		$key=$this->cfg['authSessions']['keyName'];
		return setCookie($key,null,time());
	}
	
	function throw401() {
		echo wakTemplateFeed($this->cfg['templates']['401']);
		wakShutDown();
	}
	function throw403() {
		echo wakTemplateFeed($this->cfg['templates']['403']);
		wakShutDown();
	}
	
	function throwLogout() {
		echo wakTemplateFeed($this->cfg['templates']['logout']);
		wakShutDown();
	}
	
	// add all disposable information (user, session etc) to constants
	function setConstants() {
		if (isset($this->user['id']) and !defined('USER_ID')) define('USER_ID',$this->user['id']);
		if (isset($this->user['screen_name']) and !defined('USER_SCREEN_NAME')) define('USER_SCREEN_NAME',$this->user['screen_name']);
		if (isset($this->session['key']) and !defined('AUTH_SESSION_KEY')) define('AUTH_SESSION_KEY',$this->session['key']);
		// if (isset($this->user['id']) and !defined('USER_ID')) define('USER_ID',$this->user['id']);
	}
}
?>
